package org.chaiyi.template.core.framework.swagger;


import io.swagger.v3.oas.models.media.StringSchema;
import io.swagger.v3.oas.models.parameters.Parameter;
import org.chaiyi.template.core.common.contract.ContractInfo;
import org.chaiyi.template.core.common.contract.ContractorMethodName;
import org.chaiyi.template.core.common.repository.QueryInfo;
import org.springframework.http.HttpMethod;

import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentLinkedDeque;

/**
 * 路由函数中的接口信息
 *
 * @author Gong.Yang
 */
public class RouterFunctionOperationContext {

    private RouterFunctionOperationContext() {
    }

    private static final ConcurrentLinkedDeque<OperationApiInfo> operationApiInfos = new ConcurrentLinkedDeque<>();
    private static final List<Parameter> baseParameter = List.of(
            new Parameter().in("path").name("tenantId").required(true).schema(new StringSchema()),
            new Parameter().in("path").name("buCode").required(true).schema(new StringSchema()));

    private static final Parameter pathIdParameter = new Parameter().in("path").name("id").required(true).schema(new StringSchema());
    private static final Map<String, ApiInfoCreator> map = Map.of(
            ContractorMethodName.CREATE, contractInfo -> OperationApiInfo.builder().method(HttpMethod.POST).summary("创建实体")
                    .tag(contractInfo.getName()).path(contractInfo.getPath())
                    .requestBody(contractInfo.getEntity())
                    .responseBody(contractInfo.getEntity())
                    .build()
                    .addParameters(baseParameter),
            ContractorMethodName.COUNT, contractInfo -> OperationApiInfo.builder().method(HttpMethod.POST).summary("获取数量")
                    .tag(contractInfo.getName()).path(contractInfo.getPath() + "/count")
                    .requestBody(QueryInfo.class)
                    .responseBody(Long.class)
                    .build()
                    .addParameters(baseParameter),
            ContractorMethodName.DELETE, contractInfo -> OperationApiInfo.builder().method(HttpMethod.DELETE).summary("删除实体")
                    .tag(contractInfo.getName()).path(contractInfo.getPath() + "/{id}")
                    .responseBody(contractInfo.getEntity())
                    .build()
                    .addParameters(baseParameter)
                    .addParameter(pathIdParameter),
            ContractorMethodName.QUERY, contractInfo -> OperationApiInfo.builder().method(HttpMethod.POST).summary("查询")
                    .tag(contractInfo.getName()).path(contractInfo.getPath() + "/query")
                    .requestBody(QueryInfo.class)
                    .responseBody(contractInfo.getEntity()).resIsArray(true)
                    .build()
                    .addParameters(baseParameter),
            ContractorMethodName.MODIFY, contractInfo -> OperationApiInfo.builder().method(HttpMethod.PUT).summary("全量更新")
                    .tag(contractInfo.getName()).path(contractInfo.getPath())
                    .requestBody(QueryInfo.class)
                    .responseBody(contractInfo.getEntity())
                    .build()
                    .addParameters(baseParameter),
            ContractorMethodName.FIND_BY_ID, contractInfo -> OperationApiInfo.builder().method(HttpMethod.GET).summary("通过ID获取详情")
                    .tag(contractInfo.getName()).path(contractInfo.getPath() + "/getById/{id}")
                    .responseBody(contractInfo.getEntity())
                    .build()
                    .addParameters(baseParameter)
                    .addParameter(pathIdParameter)

    );


    public static void push(ContractInfo contractInfo, String methodName) {
        OperationApiInfo info = map.get(methodName).getInfo(contractInfo);
        info.setOperationId(contractInfo.getRepositoryName() + "_" + methodName);
        operationApiInfos.push(info);
    }

    public static OperationApiInfo pop() {
        return operationApiInfos.isEmpty() ? null : operationApiInfos.pop();
    }

    public static interface ApiInfoCreator {
        OperationApiInfo getInfo(ContractInfo contractInfo);
    }
}
